package cn.wolfcode.luowowo.redis.srevice.impl;

import cn.wolfcode.luowowo.domain.Strategy;
import cn.wolfcode.luowowo.redis.RedisKey;
import cn.wolfcode.luowowo.redis.StrategyStatisVO;
import cn.wolfcode.luowowo.redis.srevice.IStrategyRedisSrevice;
import cn.wolfcode.luowowo.service.IStrategyService;
import cn.wolfcode.luowowo.util.DateUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 统计数据在redis里面进行操作的服务类
 */
@Service
public class StrategyRedisServiceImpl implements IStrategyRedisSrevice {
    
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private IStrategyService strategyService;
    
    //查询用户的收藏集合
    @Override
    public List<String> userCollectList(String userId) {
        List<String> arrayList = new ArrayList<>();
        //拼接key
        String key = RedisKey.USER_COLLECT_KEY.join(userId);
        if (redisTemplate.hasKey(key)) {
            //获取value
            String collect = redisTemplate.opsForValue().get(key);
            //转换成list集合
            arrayList = JSON.parseArray(collect, String.class);
        }
        return arrayList;
    }
    
    //将统计数据放在redis中
    @Override
    public void increaseStrategyStatis(String sid, int num) {
        //调用方法获取vo对象  是有值得
        StrategyStatisVO vo = this.getStrategyStatis(sid);
        //然后给他+1
        vo.setViewnum(vo.getViewnum() + 1);
        //然后设置回redis中,就是本类中的方法
        this.setStrategyStatis(vo);
    }
    
    //增加一个评论的数量
    @Override
    public void increaseStrategyCommentStatis(String strategyId) {
        //调用方法获取vo对象  是有值得
        StrategyStatisVO vo = this.getStrategyStatis(strategyId);
        //然后给他+1
        vo.setReplynum(vo.getReplynum() + 1);
        //然后设置回redis中,就是本类中的方法
        this.setStrategyStatis(vo);
    }
    
    //判断收藏的方法
    @Override
    public Boolean strategyFavornumStatis(String sid, String id) {
        //收藏的逻辑   判断用的是攻略来存放用户的id  还是用户来存放攻略的id
        //站在用户的角度来说是用用户来存放攻略的id,这样也能为后面做用户的收藏起作用
        //所以用的是用户存放攻略id的方式.uid作为这个集合的id.存在在redis中.攻略的集合作为value,uid加前缀做key
        String key = RedisKey.USER_COLLECT_KEY.join(id);
        //创建一个空的集合 放用户收藏的攻略
        List<String> collect = new ArrayList<>();
        //判断的方法就是传攻略的id  去用户的redis的收藏集合中判断是否存在这个攻略id
        if (redisTemplate.hasKey(key)) {
            //key存在说明redis里面是有收藏的集合的
            String list = redisTemplate.opsForValue().get(key);
            //将获取到的value塞进空的集合中  String.class代表的是集合的泛型,里面装的全部都是string类型的攻略id
            collect = JSON.parseArray(list, String.class);
        }
        //判断一下攻略id非空才进行下面的操作
        StrategyStatisVO vo = this.getStrategyStatis(sid);
        //开始判断集合中是否存在传进来的攻略id
        if (collect.contains(sid)) {
            //存在,就是取消收藏,收藏数-1,删除这个攻略的id
            vo.setFavornum(vo.getFavornum() - 1);
            //删除攻略id
            collect.remove(sid);
        } else {
            //不存在,就是收藏,收藏数+1,增加这个攻略的id
            vo.setFavornum(vo.getFavornum() + 1);
            //增加一个攻略id
            collect.add(sid);
        }
        
        //然后将vo设置到redis中去
        this.setStrategyStatis(vo);
        //最后将collect作为value,存到redis里面去
        redisTemplate.opsForValue().set(key, JSON.toJSONString(collect));
        //返回的方式可以用设置后的
        return collect.contains(sid);
    }
    
    //判断这个攻略id作为key是否存在于redis中
    //true:存在 跳过初始化循环
    //false:不存在 继续初始化
    @Override
    public boolean isStrategyKey(String id) {
        //拼接key
        String key = RedisKey.STRATEGY_STATIS_KEY.join(id);
        return redisTemplate.hasKey(key);
    }
    
    //顶/点赞的增加操作 与判断
    @Override
    public Boolean saveThumbsupnum(String sid, String uid) {
        //首先用户与攻略的关系其实是可以成为多对多的关系
        //一个攻略可以被多个用户顶,一个用户可以顶多个攻略,所以就在这个条件下进行判断,设置一个key,封装一个用户的id与一个攻略的Id.
        //这个key是灵活的 用户的id与攻略的id是没有固定的,
        String key = RedisKey.USER_STRATEGY_THUMBSUPNUM_KEY.join(sid, uid);
        //存在就是代表已经顶过了,需要明天再来
        if (redisTemplate.hasKey(key)) {
            return false;
        } else {
            //不存在就是说明没有顶过,可以定,并且增加一个key到redis中,并且这个攻略的顶加1
            //增加一个key到redis里面 value就随便设置了 注意判断的是Key,另外还要设置有效时机
            
            //设置一个时间戳
            Date now = new Date();
            
            //设置一个时间在当前时间到今天的最后一秒
            Date enw = DateUtil.getEndDate(now);
            
            //调用老师给的时间算法 得出到今天最后一秒的相差时间
            long time = DateUtil.getDateBetween(enw, now);
            redisTemplate.opsForValue().set(key, JSON.toJSONString(1), time, TimeUnit.SECONDS);
            
            //给vo对象里面的点赞数+1
            StrategyStatisVO vo = this.getStrategyStatis(sid);
            vo.setThumbsupnum(vo.getThumbsupnum() + 1);
            //然后设置vo
            this.setStrategyStatis(vo);
            return true;
        }
    }
    
    //设置vo到redis中去
    @Override
    public void setStrategyStatis(StrategyStatisVO vo) {
        //获取一个带有前缀的key 拼接的是攻略的id
        String join = RedisKey.STRATEGY_STATIS_KEY.join(vo.getStrategyId());
        //设置到redis中去
        redisTemplate.opsForValue().set(join, JSON.toJSONString(vo));
    }
    
    //通过攻略的id获取对应的vo对象
    @Override
    public StrategyStatisVO getStrategyStatis(String sid) {
        //1,拼接key
        String key = RedisKey.STRATEGY_STATIS_KEY.join(sid);
        StrategyStatisVO vo = null;
        //2.判断key是否存在
        if (!redisTemplate.hasKey(key)) {
            //3.不存在就是需要初始化一个vo对象,添加到key中
            vo = new StrategyStatisVO();
            //初始化就是获取攻略里面的所有的统计数据放进空的vo对象中去
            Strategy strategy = strategyService.get(sid);
            //使用beanutil方法复制过去
            BeanUtils.copyProperties(strategy, vo);
            //攻略id需要单独设置
            vo.setStrategyId(strategy.getId());
        } else {
            //4.存在就= ,然后重新设置回redis中
            //获取key对应的value
            String vos = redisTemplate.opsForValue().get(key);
            //将获取的value封装进对应的类中
            vo = JSON.parseObject(vos, StrategyStatisVO.class);
        }
        //5.返回vo对象,
        return vo;
    }
    
    //分享微博增加次数
    @Override
    public Boolean saveSharenum(String sid) {
        //调用方法获取vo对象  是有值得
        StrategyStatisVO vo = this.getStrategyStatis(sid);
        //然后给他+1
        vo.setSharenum(vo.getSharenum() + 1);
        //然后设置回redis中,就是本类中的方法
        this.setStrategyStatis(vo);
        return true;
    }
    
    @Override
    public List<StrategyStatisVO> selectStrategyVoByPrefix() {
        //设置一个空的用来存储vo对象的集合
        List<StrategyStatisVO> list = new ArrayList<>();
        //先拼接key
        String key = RedisKey.STRATEGY_STATIS_KEY.join("*");
        //通过拼接除了的key去查询所有的vo对象
        Set<String> keys = redisTemplate.keys(key);
        //循环,将查询出来的value全部转换从指定的对象
        for (String s : keys) {
            //根据key查出指定的value
            String vo = redisTemplate.opsForValue().get(s);
            //然后将查出的value转换成对象存进list集合中
            list.add(JSON.parseObject(vo,StrategyStatisVO.class));
        }
        //返回
        return list;
    }
}
